const removeDuplicates = arr=>{
    let map = new Map();
    arr.forEach(element => {
       map.set(JSON.stringify(element),element) 
    });
    return [...map.values()]
}

// 测试
console.log(removeDuplicates([123, "meili", "123", "mogu", 123])) 
// [123, "meili", "123", "mogu"]
console.log(removeDuplicates([123, [1, 2, 3], [1, "2", 3], [1, 2, 3], "meili"]))
// [123, [1, 2, 3], [1, "2", 3], "meili"]
console.log(removeDuplicates([123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"]))
// [123, {a: 1}, a: {b: 1}, {a: "1"}, "meili"]
console.log(removeDuplicates([{a:1, b:2},{b:2,a:1},123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili"]))
//[ { a: 1, b: 2 },{ b: 2, a: 1 },123, { a: 1 },{ a: { b: 1 } },{ a: '1' },'meili' ]

// 获取类型
const getType = (function() {
    const class2type = { '[object Boolean]': 'boolean', '[object Number]': 'number', '[object String]': 'string', '[object Function]': 'function', '[object Array]': 'array', '[object Date]': 'date', '[object RegExp]': 'regexp', '[object Object]': 'object', '[object Error]': 'error', '[object Symbol]': 'symbol' }

    return function getType(obj) {
        if (obj == null) {
            return obj + ''
        }
        // javascript高级程序设计中提供了一种方法,可以通用的来判断原始数据类型和引用数据类型
        const str = Object.prototype.toString.call(obj)
        return typeof obj === 'object' || typeof obj === 'function' ? class2type[str] || 'object' : typeof obj
    };
})();

/**
 * 判断两个元素是否相等
 * @param {any} o1 比较元素
 * @param {any} o2 其他元素
 * @returns {Boolean} 是否相等
 */
const isEqual = (o1, o2) => {
    const t1 = getType(o1)
    const t2 = getType(o2)

    // 比较类型是否一致
    if (t1 !== t2) return false
    
    // 类型一致
    if (t1 === 'array') {
        // 首先判断数组包含元素个数是否相等
        if (o1.length !== o2.length) return false 
        // 比较两个数组中的每个元素
        return o1.every((item, i) => {
            // return item === target
            return isEqual(item, o2[i])
        })
    }

    if (t2 === 'object') {
        // object类型比较类似数组
        const keysArr = Object.keys(o1)
        if (keysArr.length !== Object.keys(o2).length) return false
        // 比较每一个元素
        return keysArr.every(k => {
            return isEqual(o1[k], o2[k])
        })
    }

    return o1 === o2
}

// 数组去重
const removeDuplicates_L = (arr) => {
    return arr.reduce((accumulator, current) => {
        const hasIndex = accumulator.findIndex(item => isEqual(current, item))
        if (hasIndex === -1) {
            accumulator.push(current)
        }
        return accumulator
    }, [])
}

// 测试
console.log(removeDuplicates_L([123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili", {a:1, b:2}, {b:2, a:1}]))
// [123, {a: 1}, a: {b: 1}, {a: "1"}, "meili", {a: 1, b: 2}]
   
    

//去重算法
function keySortedObjectStringify(obj){
    const newObj = {};
    Object.keys(obj).sort().forEach(key => {
        const item = obj[key];
        let stringifyItem = item;
        if(typeof item === 'object') {
            if(Array.isArray(item)) {
                stringifyItem = JSON.stringify(item);
            } else {
                stringifyItem = keySortedObjectStringify(item);
            }
        }
        newObj[key] = stringifyItem;
    })
    return JSON.stringify(newObj);
}
function removeDuplication(arr){
    const res = [];
    const map = {};
    for(const item of arr) {
        let stringifyItem = item;
        if(typeof item === 'object') {
            if(Array.isArray(item)) {
                stringifyItem = JSON.stringify(item);
            } else {
                stringifyItem = keySortedObjectStringify(item);
            }
        }
        if(!map[stringifyItem]) {
            map[stringifyItem] = true;
            res.push(item);
        }
    }
    console.log(map,'map')
    return res;
}
    
  // 测试
console.log(removeDuplication([123, {a: 1}, {a: {b: 1}}, {a: "1"}, {a: {b: 1}}, "meili", {a:1, b:2}, {b:2, a:1}]))
// [123, {a: 1}, a: {b: 1}, {a: "1"}, "meili", {a: 1, b: 2}] 
    
    
    
 
  